﻿using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TradingServer.Core.Entities;
using System.Threading;

namespace UnitTests
{
	/// <summary>
	/// Summary description for UnitTest1
	/// </summary>
	[TestClass]
	public class SimpleTrade
	{
		public Security Security;
		public OrderGlass Glass;

		[TestInitialize]
		public void Startup()
		{
			Security = new Security("LKOH", 10);
			Glass = OrderGlassFactory.Get(Security);
		}

		[TestCleanup]
		public void Shutdown()
		{
			Glass.Clear();
		}

		[TestMethod]
		public void OrderEquality()
		{
			Order buy = new Order(OrderType.Buy, Security, 10, 100.10M);
			Order sell = new Order(OrderType.Sell, Security, 10, 100.10M);

			Assert.AreNotEqual(buy, sell);
			Assert.AreEqual(buy, buy);

			List<Order> list = new List<Order> { buy, sell };
			Assert.AreEqual(1, list.Count(item => item.Id == buy.Id));
			list.Remove(buy);
			Assert.AreEqual(0, list.Count(item => item.Id == buy.Id));
		}

		[TestMethod]
		public void RemoveOrder()
		{
			Order buy = new Order(OrderType.Buy, Security, 10, 100.10M);
			buy.Put();
			buy.Cancel();

			Order sell = new Order(OrderType.Sell, Security, 10, 100.10M);
			sell.Put();
			sell.Cancel();

			Assert.IsTrue(buy.State == OrderState.Canceled);
			Assert.IsTrue(sell.State == OrderState.Canceled);
		}

		[TestMethod]
		public void OrdersWithSamePrice()
		{
			Order buy = new Order(OrderType.Buy, Security, 10, 100.10M);
			Order sell = new Order(OrderType.Sell, Security, 10, 100.10M);
			AutoResetEvent evt = new AutoResetEvent(false);

			buy.Put();
			buy.StateChanged += (order, args) => { evt.Set(); };
			sell.Put();
			Assert.IsTrue(evt.WaitOne(TimeSpan.FromMilliseconds(100)));
		}

		[TestMethod]
		public void BuyPriceHigherSellPrice()
		{
			Order buy = new Order(OrderType.Buy, Security, 10, 100.20M);
			Order sell = new Order(OrderType.Sell, Security, 10, 100.10M);
			AutoResetEvent evt = new AutoResetEvent(false);

			buy.Put();
			buy.StateChanged += (order, args) => { evt.Set(); };
			sell.Put();
			Assert.IsTrue(evt.WaitOne(TimeSpan.FromMilliseconds(100)));
		}

		[TestMethod]
		public void BuyPriceLowerSellPrice()
		{
			Order buy = new Order(OrderType.Buy, Security, 10, 100.10M);
			Order sell = new Order(OrderType.Sell, Security, 10, 100.20M);
			AutoResetEvent evt = new AutoResetEvent(false);

			buy.Put();
			buy.StateChanged += (order, args) => { evt.Set(); };
			sell.Put();
			Assert.IsFalse(evt.WaitOne(TimeSpan.FromMilliseconds(100)));
		}

		[TestMethod]
		public void BuyMarketPrice()
		{
			Order buy = new Order(OrderType.Buy, Security, 10);
			Order sell = new Order(OrderType.Sell, Security, 10, 100.10M);
			AutoResetEvent evt = new AutoResetEvent(false);
			buy.StateChanged += (order, args) => { evt.Set(); };

			buy.Put();
			sell.Put();
			Assert.IsTrue(evt.WaitOne(TimeSpan.FromMilliseconds(100)));
			Glass.Clear();

			buy = new Order(OrderType.Buy, Security, 10);
			sell = new Order(OrderType.Sell, Security, 10, 100.20M);
			buy.StateChanged += (order, args) => { evt.Set(); };

			sell.Put();
			buy.Put();
			Assert.IsTrue(evt.WaitOne(TimeSpan.FromMilliseconds(100)));
		}
	}
}
